#ifndef LOGGER_H
#define LOGGER_H
#include <iostream>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/Category.hh>
using namespace std;
using namespace log4cpp;

#define LOG_WARN(msg) Logger::getInstance()->warn(__FILE__,__LINE__,__FUNCTION__,msg)
#define LOG_ERROR(msg) Logger::getInstance()->error(__FILE__,__LINE__,__FUNCTION__,msg)
#define LOG_DEBUG(msg) Logger::getInstance()->debug(__FILE__,__LINE__,__FUNCTION__,msg)
#define LOG_INFO(msg) Logger::getInstance()->info(__FILE__,__LINE__,__FUNCTION__,msg)




class Logger{
public:

    void warn(const char * file, int line, const char * func, const char * msg){
         _root->warn("[%s:%d] %s: %s", file, line, func, msg);
    }
    void error(const char * file, int line, const char * func, const char * msg){
         _root->error("[%s:%d] %s: %s", file, line, func, msg);
    }
    void debug(const char * file, int line, const char * func, const char * msg){
         _root->debug("[%s:%d] %s: %s", file, line, func, msg);
    }
    void info(const char * file, int line, const char * func, const char * msg){
         _root->info("[%s:%d] %s: %s", file, line, func, msg);
    }

    static Logger * getInstance(){
        if(_pInstance == nullptr){
            _pInstance = new(Logger);
            //设置日志布局
            PatternLayout *o_pt = new PatternLayout();
            o_pt->setConversionPattern("%d [%p] - %m%n");
            PatternLayout *file_pt = new PatternLayout();
            file_pt->setConversionPattern("%d [%p] - %m%n");

            //设置输出器
            //输出到屏幕
            OstreamAppender *os = new OstreamAppender("console", &cout);
            os->setLayout(o_pt);
            //输出到日志文件
            FileAppender *fi =new FileAppender("defalt","system.log");
            fi->setLayout(file_pt);

            //设置根模块日志记录器,并且输出到控制台和文件
            _root = & Category::getRoot();
            _root->addAppender(os);
            _root->addAppender(fi);
            _root->setPriority(Priority::DEBUG);
            return _pInstance;
        }
        return _pInstance;
    }
    static void destroy(){
        if(_pInstance != nullptr){
            delete _pInstance;
            Category::shutdown();
            _pInstance = nullptr;
            _root = nullptr;
        }

    }

private:
    Logger(){

    }

    ~Logger(){
    }
    Logger(const Logger &) = delete;
    Logger & operator=(const Logger &) = delete;
    static Logger * _pInstance;
    static Category * _root;
};
Logger * Logger::_pInstance = nullptr;
Category * Logger::_root = nullptr;

#endif
